/*
 * Copyright (C) 2016 Bilibili
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bilibili.draweetext;

import static com.bilibili.draweetext.util.Constants.INT_0;
import static com.bilibili.draweetext.util.Constants.INT_1;
import static com.bilibili.draweetext.util.Constants.INT_2;
import static com.bilibili.draweetext.util.Constants.INT_3;
import static com.bilibili.draweetext.util.Constants.INT_4;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.components.element.Element;
import ohos.app.Context;

/**
 * Like {@link com.facebook.drawee.view.DraweeView} that displays drawables {@link DraweeSpan} but surrounded with text.
 */
public class DraweeTextView extends Text implements Component.BindStateChangedListener, ElementChangeListener {
    private DraweeSpan[] spanArray = new DraweeSpan[INT_4];

    public DraweeTextView(Context context) {
        super(context);
        init();
    }

    public DraweeTextView(Context context, AttrSet attrs) {
        super(context, attrs);
        init();
    }

    public DraweeTextView(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setBindStateChangedListener(this);
    }

    @Override
    public void setText(String text) {
        super.setText(text);
    }

    /**
     * Set the elements around the text
     *
     * @param left element
     * @param top element
     * @param right element
     * @param bottom element
     */
    public void setAroundElements(DraweeSpan left, DraweeSpan top, DraweeSpan right, DraweeSpan bottom) {
        spanArray[INT_0] = left;
        spanArray[INT_1] = top;
        spanArray[INT_2] = right;
        spanArray[INT_3] = bottom;
        notifyElementChanged();
        onAttach();
    }

    @Override
    public void invalidate() {
        super.invalidate();
    }

    @Override
    public void onComponentBoundToWindow(Component component) {
        onAttach();
    }

    /**
     * Submits request to load the image for each element
     */
    public void onAttach() {
        for (DraweeSpan span : spanArray) {
            if (span != null) {
                span.onAttach(this);
            }
        }
    }

    /**
     * Detach all of the DraweeSpans in text
     */
    final void onDetach() {
        for (DraweeSpan span : spanArray) {
            if (span != null) {
                Element element = span.getDrawable();
                // reset callback first
                if (element != null) {
                    element.release();
                }
                span.onDetach();
            }
        }
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        onDetach();
    }

    @Override
    public void notifyElementChanged() {
        Element[] elements = new Element[INT_4];
        for (int index = 0; index < spanArray.length; index++) {
            if (spanArray[index] != null) {
                elements[index] = spanArray[index].getDrawable();
            }
            setAroundElements(elements[INT_0], elements[INT_1], elements[INT_2], elements[INT_3]);
        }
    }
}
